// Fill out your copyright notice in the Description page of Project Settings.


#include "AttackComponentBaseCpp.h"
#include "NPCBaseCpp.h"
#include "SmallGoblinBaseCpp.h"
#include "FlyingEyeBaseCpp.h"
#include "DemonBaseCpp.h"
#include "PlayerBaseCpp.h"
#include "PlayerStateBaseCpp.h"
#include "GameModeBaseCpp.h"

// Sets default values for this component's properties
UAttackComponentBaseCpp::UAttackComponentBaseCpp()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
	ComboAmount = 3;
	UseMagicBuffer = false;
}


// Called when the game starts
void UAttackComponentBaseCpp::BeginPlay()
{
	Super::BeginPlay();

	// ...
	CurrentPlayerState = GetWorld()->GetFirstPlayerController()->GetPlayerState<APlayerStateBaseCpp>();
}


// Called every frame
void UAttackComponentBaseCpp::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// ...
	CurrentPlayerState->IncreasePower(CurrentPlayerState->GetPowerIncreasingSpeed() * DeltaTime);
}

void UAttackComponentBaseCpp::Attack(const TArray<FHitResult>& NPCs)
{
	TSet<FString> IdSet;
	for (FHitResult Result : NPCs)
	{
		if (Result.GetActor() != nullptr && Result.GetActor()->ActorHasTag(FName("NPC")))
		{
			ANPCBaseCpp* NPCBase = Cast<ANPCBaseCpp>(Result.GetActor());
			if (NPCBase == nullptr)
			{
				return;
			}
			const FString CurrentNPCId = NPCBase->GetNPCId();
			if (IdSet.Contains(CurrentNPCId))
			{
				continue;
			}
			IdSet.Emplace(CurrentNPCId);
			ApplyDamage(Result.GetActor(), EAttackMode::E_BasicAttack);
		}
	}
}

void UAttackComponentBaseCpp::SetParentPlayer(APlayerBaseCpp* Player)
{
	ParentPlayer = Player;
}

void UAttackComponentBaseCpp::AttackPro() const
{
	if (CurrentPlayerState->GetPower() - CurrentPlayerState->GetPowerDecreasingSpeed() > 0.0f)
	{
		AGameModeBaseCpp* CurrentGameMode = Cast<AGameModeBaseCpp>(UGameplayStatics::GetGameMode(GetWorld()));
		CurrentGameMode->StartAttackPro(ComboAmount);
		CurrentPlayerState->DecreasePower(CurrentPlayerState->GetPowerDecreasingSpeed());
	}
}

void UAttackComponentBaseCpp::ApplyDamage(AActor* DamageTaker, const EAttackMode AttackMode)
{
	float DamageValue;
	switch (AttackMode)
	{
	case EAttackMode::E_BasicAttack:
		{
			DamageValue = CurrentPlayerState->GetBaseDamage();
			break;
		}
	case EAttackMode::E_ProAttack:
		{
			DamageValue = CurrentPlayerState->GetProDamage();
			if (UseMagicBuffer)
			{
				DamageValue *= 2.0f;
			}
			break;
		}
	default:
		{
			DamageValue = 0.0f;
			break;
		}
	}
	if (DamageTaker->ActorHasTag(FName("SmallGoblin")))
	{
		ASmallGoblinBaseCpp* NPC = Cast<ASmallGoblinBaseCpp>(DamageTaker);
		if (NPC != nullptr)
		{
			if (NPC->GetHP() > 0.0f)
			{
				UGameplayStatics::ApplyDamage(NPC, DamageValue, ParentPlayer->GetController(), ParentPlayer, nullptr);
				if (NPC->GetCurrentHP() <= 0.0)
				{
					NPC->SetNPCDead();
				}
			}
		}
	}
	else if (DamageTaker->ActorHasTag(FName("FlyingEye")))
	{
		AFlyingEyeBaseCpp* NPC = Cast<AFlyingEyeBaseCpp>(DamageTaker);
		if (NPC != nullptr)
		{
			UGameplayStatics::ApplyDamage(NPC, DamageValue, ParentPlayer->GetController(), ParentPlayer, nullptr);
			if (NPC->GetCurrentHP() <= 0.0)
			{
				NPC->SetNPCDead();
			}
		}
	}
	else if (DamageTaker->ActorHasTag(FName("Demon")))
	{
		ADemonBaseCpp* NPC = Cast<ADemonBaseCpp>(DamageTaker);
		if (NPC != nullptr)
		{
			UGameplayStatics::ApplyDamage(NPC, DamageValue, ParentPlayer->GetController(), ParentPlayer, nullptr);
			if (NPC->GetCurrentHP() <= 0.0)
			{
				NPC->SetNPCDead();
			}
		}
	}
}

void UAttackComponentBaseCpp::SetUseMagicBuffer(const bool Use)
{
	UseMagicBuffer = Use;
}

bool UAttackComponentBaseCpp::GetUseMagicBuffer() const
{
	return UseMagicBuffer;
}

